package com.turman.common.net.support

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.google.gson.Gson
import com.turman.common.net.model.ApiResponse
import com.turman.common.net.model.DataResult
import com.turman.common.net.model.UNKNOWN_ERROR_CODE
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import retrofit2.await
import retrofit2.awaitResponse
import java.io.IOException
import java.lang.RuntimeException

/**
 * 请求库的相关扩展方法
 */


/**
 * okhttp的Call执行异步，并转化为livedata可观察结果
 */
inline fun <reified T> Call.toLiveData():LiveData<T?> {
    val live = MutableLiveData<T>()
    this.enqueue(object :Callback{
        override fun onFailure(call: Call, e: IOException) {
            live.postValue(null)
        }

        override fun onResponse(call: Call, response: Response) {
            if (response.isSuccessful) {
                response.toEntity<T>()   //这也是可扩展，下面注释
            }
        }
    })
    return live
}

/**
 * 将response的对象，转化为需要的对象类型，也就是将body.string转为entity
 */
inline fun <reified T> Response.toEntity():T? {
    if (!isSuccessful) return null
    //单独处理返回字符串的情况
    if (T::class.java.isAssignableFrom(String::class.java)) {
        return kotlin.runCatching {
            this.body?.string()
        }.getOrNull() as T?
    }
    //处理返回json字符串的情况
    return kotlin.runCatching {
        Gson().fromJson(this.body?.string(),T::class.java)
    }.onFailure {
        it.printStackTrace()
    }.getOrNull()
}

/**
 * retrofit2的call扩展，执行异步，并转化为livedata可观察结果
 */
fun <T:Any> retrofit2.Call<T>.toLiveData():LiveData<T?> {
    val live = MutableLiveData<T>()

    this.enqueue(object:retrofit2.Callback<T>{
        override fun onResponse(call: retrofit2.Call<T>, response: retrofit2.Response<T>) {
            val value:T? = if (response.isSuccessful){
                response.body()
            } else {
                null
            }
            live.postValue(value)
        }

        override fun onFailure(call: retrofit2.Call<T>, t: Throwable) {
            live.postValue(null)
        }
    })
    return live
}

/**
 * 扩展retrofit返回数据，调用await，并catch超时异常
 */
suspend fun <T:Any> retrofit2.Call<T>.serverData():DataResult<T> {
    var result:DataResult<T> = DataResult.Loading

    kotlin.runCatching {
        this.await()
    }.onFailure {
        result = DataResult.Error(RuntimeException(it))
        it.printStackTrace()
    }.onSuccess {
        result = DataResult.Success(it)
    }.getOrNull()

    return result
}

/**
 * 扩张retrofit的返回数据，调用await，并catch超时异常
 */
suspend fun <T:Any> retrofit2.Call<T>.serverRsp():ApiResponse<T> {
    var result:ApiResponse<T>

    val response:retrofit2.Response<T> = kotlin.runCatching {
        this.awaitResponse()
    }.onFailure {
        result = ApiResponse.create(UNKNOWN_ERROR_CODE,it)
        it.printStackTrace()
    }.getOrThrow()

    result = ApiResponse.create(response)
    return result
}












